// Fill out your copyright notice in the Description page of Project Settings.

#pragma once
#include "NVIDIAGfeSDKPrivatePCH.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include <gfesdk/bindings/cpp/highlights/highlights_types_cpp.h>
#include "NVIDIAGfeSDKTypes.h"
#include "HighLightBlueprint.generated.h"

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_UCLASS_BODY()
public:
	// This function should be called periodically.
	// It is used to receive callbacks.
	// Can be called in Tick event
	UFUNCTION(BlueprintCallable, Category = "Shadowplay Highlights")
	static void Poll();
	// This function is for convenience
	// It chesks if the permissions to use Video or Screenshots functions are granted
	// It returns the actual enumeration values for each function
	UFUNCTION(BlueprintCallable, Category = "Shadowplay Highlights")
	static void ChekIfHighlightsAvailable(const FGfeSDKCreateResponse& InitProperties, bool &VideoGranted, bool &ScreenshotsGranted, EGfeSDKPermission &Video, EGfeSDKPermission &Screenshots);
};


//---------------------------------------------------------------------------

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHighlightsCallback);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHighlightsOperationResultCallback, EGfeSDKReturnCode, GfeSdkReturnCode);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHighlightsInitCallback, EGfeSDKReturnCode, GfeSdkReturnCode, FGfeSDKCreateResponse, GfeSdkProperties);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnGetNumberOfHighlightsCallback, EGfeSDKReturnCode, GfeSdkReturnCode, int32, NumberOfHighlights);

UCLASS()
class UInitHighlights : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful init
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsInitCallback OnSuccess;

	// Called when there is an unsuccessful init
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Initializes the Highlights client. Should be called first, all other functions will fail otherwise. Takes the game name and desired Highlights options as an input.
	// Requests Highlights permissions to recorde Video or Screenshots according to the input checkboxes
	// Use the GFE Request Permissions function if desired permissions are not granted to you.
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UInitHighlights* InitHighlights(UObject* WorldContextObject, const FString InGameName, const bool Video, const bool Screenshots);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	FCriticalSection	CS;
	UObject*			WorldContextObject;
	FString				GameName;
	TArray<EGfeSDKScope> RequestedPermissions;

	// Permissions for Highlights
	TMap<EGfeSDKScope, EGfeSDKPermission> mLastScopePermissions;
	TArray<EGfeSDKScope> mPermissionsNeeded;

	void Callback();
	void OnPermissionsChanged(FGfeSDKPermissionsChangedData const& PermissionsChangedData);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsConfigureAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Configures the highlights system and defines the highlight types. 
	// Should be called once in game (or can be called if the highlight type list changed, for example for another game type).
	// Should be called after init and before the OpenGroup functions
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsConfigureAsync* HighlightsConfigure(UObject* WorldContextObject, const FGfeSDKHighlightConfigParams& ConfigParams);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*							WorldContextObject;
	FGfeSDKHighlightConfigParams		ConfigParams;
	static void __stdcall OnConfigureCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsOpenGroupAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Opens the group of highlights
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsOpenGroupAsync* HighlightsOpenGroup(UObject* WorldContextObject, const FGfeSDKHighlightOpenGroupParams& Params);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKHighlightOpenGroupParams			Params;
	static void __stdcall OnOpenGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsCloseGroupAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Closes the group of highlights
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsCloseGroupAsync* HighlightsCloseGroup(UObject* WorldContextObject, const FString& GroupId, const bool& DestroyHighlights);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKHighlightCloseGroupParams		Params;
	static void __stdcall OnCloseGroupCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsSetScreenshotAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Takes screenshot of the game
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsSetScreenshotAsync* HighlightsSetScreenshot(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKHighlightScreenshotParams		Params;
	static void __stdcall OnSetScreenshotCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsSetVideoAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Records the video of the gameplay
	// GroupID is the name of the group this highlight is related to
	// HighlightID is the name of the Highlight
	// StartDelta and EndDelta are the time range in miliseconds from the current moment.
	// For example StartDelta can be set to -2000 and EndDelta to 3000 - that corresponds to {get the video of two seconds before this moment and record 3 seconds more from this moment}
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsSetVideoAsync* HighlightsSetVideo(UObject* WorldContextObject, const FString& GroupId, const FString& HighlightId, const int32& StartDelta, const int32& EndDelta);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKHighlightVideoParams				Params;
	static void __stdcall OnSetVideoCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsSummaryAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Shows the Shadowplay Highlights Summary interface
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsSummaryAsync* HighlightsOpenSummary(UObject* WorldContextObject, const FGfeSDKHighlightSummaryParams& Params);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKHighlightSummaryParams			Params;
	static void __stdcall OnOpenSummaryCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class UHighlightsGetNumberAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnGetNumberOfHighlightsCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Gets number of highlights recorded according to the specified input filtering values
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static UHighlightsGetNumberAsync* HighlightsGetNumberOfHighlights(UObject* WorldContextObject, const FString& GroupID, const EGfeSDKHighlightType& TagFilter, const EGfeSDKHighlightSignificance& SignificanceFilter);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKHighlightGroupView				Params;
	static void __stdcall OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, GfeSDK::NVGSDK_Highlights_NumberOfHighlights const* NumberOfHighlights, void* context);
};

//---------------------------------------------------------------------------

UCLASS()
class URequestPermissionsAsync : public UBlueprintAsyncActionBase
{
	GENERATED_BODY()
public:
	// Called when there is a successful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnSuccess;

	// Called when there is an unsuccessful query
	UPROPERTY(BlueprintAssignable)
		FOnHighlightsOperationResultCallback OnFailure;

	// Requests permissions to use the specified Shadowplay Highlights features
	// Use this function to request the permission if the InitHighlights function failed to grant the desired permissions
	// Uses Poll function to receive callbacks
	UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"), Category = "Shadowplay Highlights")
		static URequestPermissionsAsync* GFERequestPermissions(UObject* WorldContextObject, const bool Video, const bool Screenshots);

	// UBlueprintAsyncActionBase interface
	virtual void Activate() override;
	// End of UBlueprintAsyncActionBase interface

private:
	UObject*								WorldContextObject;
	FGfeSDKRequestPermissionsParams			Params;
	static void __stdcall OnGetNumberCallback(GfeSDK::NVGSDK_RetCode rt, void* context);
};